home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / muds / mordor_2.000 / mordor_2 / util / italk / italk.c
C/C++ Source or Header  |  1994-11-13  |  12KB  |  542 lines

  1. /* ITALK.C:Internet Talking:  Copyright 1991, 1992 Steven D. Wallace */
  2. /*   Public domain.  For non-commercial use only.
  3. /*                                                                         */
  4.  
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <sys/ioctl.h>
  8. #include <netinet/in.h>
  9. #include <arpa/inet.h>
  10. #include <netdb.h>
  11. #include <errno.h>
  12. #include <stdio.h>
  13. #include <sys/file.h>
  14. #include <ctype.h>
  15. #include <signal.h>
  16. #define TIOCGETP        _IOR(0, 8,struct sgttyb)/* get parameters -- gtty */
  17. #define TIOCSETP        _IOW(0, 9,struct sgttyb)/* set parameters -- stty */ 
  18. /*
  19.  * Structure for TIOCGETP and TIOCSETP ioctls.
  20.  */
  21.  
  22. #ifndef _SGTTYB_
  23. #define _SGTTYB_
  24. struct  sgttyb {
  25.         char    sg_ispeed;              /* input speed */
  26.         char    sg_ospeed;              /* output speed */
  27.         char    sg_erase;               /* erase character */
  28.         char    sg_kill;                /* kill character */
  29.         short   sg_flags;               /* mode flags */
  30. };
  31. #endif
  32. #if 1 /* 0 for computers that don't have h_addr_list in struct hostent */
  33. #define h_addr  h_addr_list[0] /* for backwards compatibilty */
  34. #endif
  35.  
  36. #define HOSTFILE ".ithost"
  37. #define FILE1 "/home/Isengard/mordor/bin/.lphost"
  38. #define SDWFILE FILE1
  39.  
  40. #define MAXMACRO 100
  41. #define MAXDIGIT 2
  42.  
  43. /* TERM.C */
  44.  
  45. extern void     new_term(), old_term();
  46. extern char     get_key(), in_key();
  47.  
  48. extern errno;
  49. int sock;
  50. int df_i = 1;
  51. int df_o = 2;
  52. char quiet = 0;
  53.  
  54. void aborting();
  55. void get_address();
  56. void split_string();
  57.  
  58. main(argc, argv)
  59. int argc;
  60. char *argv[];
  61. {
  62.   char  address[30], port[10], path[80], startup[20], macro[20], blank[80];
  63.   char  *address_ptr, *port_ptr, *startup_ptr, *macro_ptr;
  64.   int   i = 0;
  65.   char    command[MAXMACRO][80];
  66.  
  67.   address[0] = port[0] = path[0] = startup[0] = macro[0] = blank[0] = 0;
  68.   signal(SIGPIPE,SIG_IGN);
  69.  
  70.   i = 1;
  71.   if(i < argc) {
  72.     if(argv[i][0] == '-' && argv[i][1] == 'q') {
  73.       quiet = 1;
  74.       i++;
  75.     }
  76.   }
  77.   if(i < argc) {
  78.     strcpy(address, argv[i++]);
  79.     if(i < argc)
  80.       strcpy(port, argv[i++]);
  81.   }
  82.   else
  83.     get_address(address, port);
  84.  
  85.   /* determine user's pathname to their .ithost file */
  86.   sprintf(path, "%s/%s", getenv("HOME"), HOSTFILE);
  87.  
  88.   /* if no dot in address string argument, good chance it is a symbol */
  89.   if (!dot_in_string(address)) {
  90.  
  91.     address_ptr = address;
  92.  
  93.     /* if no valid port given as argument, read in new startup */
  94.     if (!*port)
  95.       port_ptr = port;
  96.     else
  97.       port_ptr = blank;
  98.  
  99.     /* then look up address in .ithost in user's home directory */
  100.     if (!read_address(path, address, address_ptr, port_ptr, startup, macro))
  101.  
  102.       /* not in their home directory, so try ~swallace/.lphost */
  103.       read_address(SDWFILE, address, address_ptr, port_ptr, startup, macro);
  104.     else
  105.  
  106.       /* lookup good, see if address is a reference to global symbol */
  107.       if (*address == '!') {
  108.  
  109.     if (*port != '!')
  110.       port_ptr = blank;
  111.  
  112.     /* if no valid startup given, read in global startup */
  113.     if (!*startup || *startup == '#')
  114.       startup_ptr = startup;
  115.     else
  116.       startup_ptr = blank;
  117.  
  118.     /* if no valid macro given, read in global startup */
  119.     if (!*macro || *macro == '#')
  120.       macro_ptr = macro;
  121.     else
  122.       macro_ptr = blank;
  123.  
  124.         read_address(SDWFILE, address + 1, address_ptr, port_ptr, startup_ptr, 
  125. macro_ptr);
  126.       }
  127.  
  128.     }
  129.  
  130.   if (*port == '#')     *port = 0;
  131.   if (*startup == '#')    *startup = 0;
  132.   if (*macro == '#')    *macro = 0;
  133.  
  134. /*  printf("addr: %s, port: %s, startup: %s, macro: %s\n", address, port, start
  135. up, macro); */
  136.  
  137.   sock = connect_sock(address, port);
  138.   if (sock == -1)
  139.     aborting(3);
  140.  
  141.   /* clear macros */
  142.   for(i=0; i != MAXMACRO; i++)
  143.     command[i][0] = 0;
  144.  
  145.   /* determine user's pathname to their .macro or whatever file */
  146.   sprintf(path, "%s/%s", getenv("HOME"), macro);
  147.  
  148.   /* read macro from user's file */
  149.   if(*macro)
  150.    if (read_macro(path, command) && !quiet)
  151.     fprintf(stderr, "Macros read from file %s.\n", path);
  152.  
  153.   if (*startup) {
  154.     sprintf(path, "%s/%s", getenv("HOME"), startup);
  155.     write_file(path);
  156.   }
  157.  
  158.   if (socket_io_handler(sock, command) == -1)
  159.     aborting(4);
  160.  
  161. }
  162.  
  163.  
  164. int connect_sock(address, port)
  165. char *address;
  166. char *port;
  167. {
  168.   int  temp_int;
  169.   char name[80];
  170.   char number[20];
  171.   unsigned long addr;
  172.   unsigned long saddr;
  173.   struct sockaddr_in sin;
  174.   struct hostent *host;
  175.  
  176.   if(isdigit(address[0])) {
  177.     if((addr = inet_addr(address)) == -1)
  178.       aborting(5);
  179.     else
  180.       saddr = ntohl(addr);
  181.       host = gethostbyaddr((char *)&saddr, sizeof(saddr), AF_INET);
  182.       if(host)
  183.         strncpy(name, host->h_name, 79);
  184.       else
  185.         strcpy(name, address);
  186.  
  187.       strcpy(number, address);
  188.   }
  189.   else {
  190.     host = gethostbyname(address);
  191.     if(!host) aborting(6);
  192.     addr = *(long *)(host->h_addr);
  193.     strcpy(name, host->h_name);
  194.  
  195.     saddr = ntohl(addr);
  196.     sprintf(number, "%d.%d.%d.%d",
  197.         (unsigned)(saddr)>>24,
  198.         (saddr & 0x00ff0000)>>16,
  199.         (saddr & 0x0000ff00)>>8,
  200.         (saddr & 0x000000ff));
  201.   }
  202.   
  203.   sin.sin_addr.s_addr = addr;
  204.   sin.sin_family = AF_INET;
  205.   sin.sin_port = htons(atoi(port) ? atoi(port) : 23);
  206.  
  207.   if(!quiet) {
  208.     if(*port)
  209.       fprintf(stderr, "Trying %s, port %s ...\n", number, port);
  210.     else
  211.       fprintf(stderr, "Trying %s ...\n", number);
  212.   }
  213.  
  214.   if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
  215.     perror("Socket");
  216.     return(-1);
  217.   }
  218.   if(connect(sock, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
  219.     perror("Connect");
  220.     return(-1);
  221.   }
  222.  
  223.   temp_int = 1;
  224.   ioctl(sock, FIONBIO, &temp_int);
  225.  
  226.   if(!quiet) {
  227.     if(*port)
  228.       fprintf(stderr, "Connected to %s, port %s.\n", name, port);
  229.     else
  230.       fprintf(stderr, "Connected to %s.\n", name);
  231.   }
  232.  
  233.   return(sock);
  234. }
  235.  
  236. int socket_io_handler(sock, command)
  237. int sock;
  238. char *command;
  239. {
  240.   int  readfds;
  241.   int  len, i;
  242.   char echo = 1;
  243.   char buf[1024];
  244.   char *temp, tc;
  245.   struct sgttyb arg;
  246.  
  247.   while(1) {
  248.     readfds = 1<<df_i | 1<<sock;
  249.  
  250.     while(!select(16, &readfds, 0, 0, 0)) ;
  251.     if(readfds & (1<<df_i)) {
  252.       len = read(df_i, buf, 1023);
  253.       if(len == 0) aborting(1);
  254.       if( ( (buf[0] >= '0') && (buf[0] <= '9') ) &&
  255.            !( (buf[MAXDIGIT] >= '0') && (buf[MAXDIGIT] <= '9') ) ) {
  256.     tc = buf[MAXDIGIT];
  257.     buf[MAXDIGIT] = 0;
  258.     i = atoi(buf);
  259.         temp = command + i*80;
  260.     if(*temp && (i < MAXMACRO)) {
  261.           if(write(sock, temp, (len = strlen(temp))) < 0) {
  262.             perror("write sock");
  263.             return(0);
  264.           }
  265.     }
  266.     else {
  267.       buf[MAXDIGIT] = tc;
  268.           if(write(sock, buf, len) < 0) {
  269.             perror("write sock");
  270.             return(0);
  271.           }
  272.     }
  273.       }
  274.       else
  275.         if(write(sock, buf, len) < 0) {
  276.           perror("write sock");
  277.           return(0);
  278.         }
  279.     }
  280.  
  281.     if(readfds & (1<<sock)) {
  282.       len = read(sock, buf, 1023);
  283.       if(len == 0) aborting(2);
  284.  
  285.       if (buf[0] == -1) {
  286.  
  287.     if (buf[1] == -5 && buf[2] == 1) {
  288.       ioctl(0,TIOCGETP,&arg);    /* Get initial setup */
  289.       arg.sg_flags &= ~(ECHO);    /* Turn off terminal ECHO */
  290.       ioctl(0,TIOCSETP,&arg);    /* Store new settings */
  291.       echo = 0;
  292.               if (len > 3) if(write(df_o, buf+3, len-3) < 0) {
  293.               perror("write terminal");
  294.               return(0);
  295.              }
  296.     }
  297.  
  298.     else if (buf[1] == -4 && buf[2] == 1) {
  299.       ioctl(0,TIOCGETP,&arg);    /* Get initial setup */
  300.       arg.sg_flags |= (ECHO);    /* Turn on terminal ECHO */
  301.       ioctl(0,TIOCSETP,&arg);    /* Store new settings */
  302.       echo = 1;
  303.               if (len > 3) if(write(df_o, buf+3, len-3) < 0) {
  304.               perror("write terminal");
  305.               return(0);
  306.              }
  307.     }
  308.  
  309.         else if(write(df_o, buf, len) < 0) {
  310.           perror("write terminal");
  311.           return(0);
  312.         }
  313.  
  314.       } /* end FF special check */
  315.  
  316.       else if(write(df_o, buf, len) < 0) {  /* no FF, so output string */
  317.         perror("write terminal");
  318.         return(0);
  319.       }
  320.  
  321.       if(!echo) {
  322.     for(i = 0; i < len-2; i++)
  323.       if(buf[i] == -1)
  324.             if(buf[i] == -1 && buf[i+1] == -4 && buf[i+2] == 1) {
  325.           ioctl(0,TIOCGETP,&arg);    /* Get initial setup */
  326.           arg.sg_flags |= (ECHO);    /* Turn on terminal ECHO */
  327.           ioctl(0,TIOCSETP,&arg);    /* Store new settings */
  328.               echo = 1;
  329.         }
  330.       } /* end no echo to echo check */
  331.  
  332.     } /* end socket out check */
  333.  
  334.   }  /* end infinite loop */
  335. } /* end io_handler */
  336.  
  337. void get_address(address, port)
  338. char *address;
  339. char *port;
  340. {
  341.   char buf[51];
  342.  
  343.   write_msg("Destination: ");
  344.   read_msg(buf,50);
  345.  
  346.   split_string(buf, address, port);
  347. }
  348.  
  349. void split_string(str_in, str_one, str_two)
  350. char *str_in;
  351. char *str_one;
  352. char *str_two;
  353. {
  354.   int i=0, j=0;
  355.  
  356.   while(str_in[i] != ' ' && str_in[i] != '\n' && str_in[i] != 0)
  357.     str_one[j++] = str_in[i++];
  358.   str_one[j]=0; j=0;
  359.   while(str_in[i] == ' ' || str_in[i] == '\n') i++;
  360.   if(str_in[i])
  361.     while(str_in[i] != 0 && str_in[i] != '\n')
  362.       str_two[j++] = str_in[i++];
  363.   str_two[j]=0;
  364. }
  365.  
  366. int dot_in_string(str)
  367. char *str;
  368. {
  369.   int i=0;
  370.  
  371.   while (str[i++] != 0)
  372.     if (str[i-1] == '.')
  373.       return(1);
  374.  
  375.   return(0);
  376. }
  377.  
  378. int read_macro(fname, command)
  379. char  *fname;
  380. char  *command;
  381. {
  382.   FILE *fp;
  383.   char buf[81];
  384.   char numbuf[21];
  385.   char *temp;
  386.   int  num, i;
  387.  
  388.   if((fp=fopen(fname, "r")) == 0)
  389.     return(0);
  390.  
  391.   while(!feof(fp)) {
  392.     fgets(buf, sizeof(buf), fp);
  393.     if(*buf == '#')
  394.       continue;
  395.     split_string(buf, numbuf, buf);
  396.  
  397.     num = atoi(numbuf);
  398.     temp = command + num*80;
  399.     if(num) {
  400.       strcpy(temp, buf);
  401.       num = strlen(temp);
  402.  
  403.       /* replace all '\' with CR/LF? */
  404.       for (i = 0; i != num; i++) {
  405.     if (temp[i] == '\\')
  406.       temp[i] = 13;
  407.       }
  408.  
  409.       /* add CR to end of string */
  410.       if (temp[num-1] != 13) {
  411.     temp[num] = 13;
  412.     num = num +1;
  413.       }
  414.       temp[num] = 0;
  415.     }
  416.   }
  417.   fclose(fp);
  418.   return(1);
  419. }
  420.  
  421. int read_address(fname, symbol, address, port, startup, macro)
  422. char  *fname;
  423. char  *symbol;
  424. char  *address;
  425. char  *port;
  426. char  *startup;
  427. char  *macro;
  428. {
  429.   FILE *fp;
  430.   char buf[81];
  431.   char cur_symbol[21];
  432.   int  i;
  433.  
  434.   if((fp=fopen(fname, "r")) == 0)
  435.     return(0);
  436.   while(!feof(fp)) {
  437.     fgets(buf, sizeof(buf), fp);/* get rest of line (address, port) */
  438.     split_string(buf, cur_symbol, buf);
  439.  
  440.     /* check to see if parameter matches current symbol in line */
  441.     for (i=0; symbol[i] != 0; i++)
  442.       if (symbol[i] != cur_symbol[i])
  443.         break;
  444.     if (symbol[i] == cur_symbol[i]) {
  445.       fclose(fp);
  446.       split_string(buf, address, buf);
  447.       if(*buf) split_string(buf, port, buf);
  448.       if(*buf) split_string(buf, startup, buf);
  449.       if(*buf) split_string(buf, macro, buf);
  450.       return(1);
  451.     } 
  452.   }
  453.   fclose(fp);
  454.   return(0);
  455. }
  456.  
  457. int write_file(path)
  458. char  *path;
  459. {
  460.   int  fd;
  461.   long count;
  462.   char buf[1024];
  463.  
  464.   fd = open(path, O_RDONLY, 0);
  465.   if(fd < 0) return(0);
  466.  
  467.   if(!quiet)
  468.     fprintf(stderr, "Sending file %s to remote host.\n", path);
  469.  
  470.   while(1) {
  471.     count = read(fd, buf, sizeof(buf));
  472.     if(count)
  473.       write(sock, buf, count);
  474.     else
  475.       break;
  476.   }
  477.   return(1);
  478. }
  479.  
  480. write_msg(str)
  481. char *str;
  482. {
  483.   write(df_o, str, strlen(str));
  484. }
  485.  
  486. write_sock(str)
  487. char *str;
  488. {
  489.   write(sock, str, strlen(str));
  490. }
  491.  
  492. read_msg(str,slen)
  493. char *str;
  494. int slen;
  495. {
  496.   int readfds;
  497.   int num=0, len;
  498.   char ch;
  499.  
  500.   do {
  501.     readfds = 1<<df_i;
  502.     while(!select(16, &readfds, 0, 0, 0)) ;
  503.     len = read(df_i, &ch, 1);
  504.     if(len == 0) aborting(0);
  505.     if(ch == 10 || num==slen-1) ch = 0;
  506.     if(ch != 13) str[num++] = ch;
  507.   } while(ch);
  508.  
  509. }
  510.  
  511. void aborting(arg)
  512. int arg;
  513. {
  514.   switch (arg) {
  515.     case 1:
  516.         fprintf(stderr, "\nConnection closed by local host.\n");
  517.         break;
  518.     case 2:
  519.         fprintf(stderr, "\nConnection closed by remote host.\n");
  520.         break;
  521.     case 3:
  522.         fprintf(stderr, "\nUnable to connect to remote host.\n");
  523.         break;
  524.     case 4:
  525.         fprintf(stderr, "\nProblems with sockets.  Connection closed.\n");
  526.         break;
  527.     case 5:
  528.         fprintf(stderr, "\nInvalid host number.\n");
  529.         break;
  530.     case 6:
  531.         fprintf(stderr, "\nInvalid host name.\n");
  532.         break;
  533.     default:
  534.           fprintf(stderr, "Connection closed (%d).\n",arg);
  535.   }
  536.   signal(SIGPIPE,SIG_IGN);
  537.   close(sock); close(df_i); close(df_o);
  538.   exit(0);
  539. }
  540.  
  541.  
  542.